00001 // Emacs Mode Line: -*- Mode:c++;-*- 00002 // ------------------------------------------------------------- 00003 /* 00004 * Copyright (c) 2013 Battelle Memorial Institute 00005 * Licensed under modified BSD License. A copy of this license can be found 00006 * in the LICENSE file in the top level directory of this distribution. 00007 */ 00008 // ------------------------------------------------------------- 00009 /** 00010 * @file nonlinear_solver.hpp 00011 * @author William A. Perkins 00012 * @date 2015-03-25 15:54:13 d3g096 00013 * 00014 * @brief 00015 * 00016 * 00017 */ 00018 // ------------------------------------------------------------- 00019 00020 #ifndef _nonlinear_solver_hpp_ 00021 #define _nonlinear_solver_hpp_ 00022 00023 #include <boost/scoped_ptr.hpp> 00024 #include "gridpack/math/nonlinear_solver_implementation.hpp" 00025 00026 namespace gridpack { 00027 namespace math { 00028 00029 // ------------------------------------------------------------- 00030 // class NonlinearSolver 00031 // ------------------------------------------------------------- 00032 /// A solver for a system of nonlinear system of equations in parallel 00033 /** 00034 * This class is used to solve a system of nonlinear equations in the form 00035 00036 * \f[ 00037 * \left[ \mathbf{J}\left( \mathbf{x} \right) \right] \Delta \mathbf{x} ~ = ~ 00038 * -\mathbf{F}\left( \mathbf{x} \right) 00039 * \f] 00040 00041 * where \f$\mathbf{J}\left( \mathbf{x} \right)\f$ is the Jacobian 00042 * matrix, \f$\mathbf{x}\f$ is the solution Vector, and 00043 * \f$\mathbf{F}\left( \mathbf{x} \right)\f$ is some Vector function 00044 * of \f$\mathbf{x}\f$. 00045 * 00046 * Users of this class must specify functions or functors that build 00047 * the \ref JacobianBuilder "Jacobian" Matrix and the \ref 00048 * FunctionBuilder "right hand side" Vector. Typically, it's best to 00049 * use functor classes or structs, since extra required information 00050 * can be available to the Matrix/Vector construction. 00051 * 00052 * Implementation ... 00053 */ 00054 template <typename T, typename I = int> 00055 class NonlinearSolverT 00056 : public NonlinearSolverInterface<T, I>, 00057 public parallel::WrappedDistributed, 00058 public utility::WrappedConfigurable, 00059 private utility::Uncopyable 00060 { 00061 public: 00062 00063 typedef typename NonlinearSolverImplementation<T, I>::VectorType VectorType; 00064 typedef typename NonlinearSolverImplementation<T, I>::MatrixType MatrixType; 00065 typedef typename NonlinearSolverImplementation<T, I>::JacobianBuilder JacobianBuilder; 00066 typedef typename NonlinearSolverImplementation<T, I>::FunctionBuilder FunctionBuilder; 00067 00068 /// Default constructor. 00069 /** 00070 * @e Collective. 00071 * 00072 * A NonlinearSolverT must be constructed simultaneously on all 00073 * processes involved in @c comm. 00074 * 00075 * @param comm communicator on which the instance is to exist 00076 * @param local_size number Jacobian rows and Vector entries to be owned by this process 00077 * @param form_jacobian function to fill the Jacobian Matrix, \f$\left[ \mathbf{J}\left( \mathbf{x} \right) \right]\f$ 00078 * @param form_function function to fill the RHS function Vector, \f$\mathbf{F}\left( \mathbf{x} \right)\f$ 00079 * 00080 * @return new NonlinearSolverT instance 00081 */ 00082 NonlinearSolverT(const parallel::Communicator& comm, 00083 const int& local_size, 00084 JacobianBuilder form_jacobian, 00085 FunctionBuilder form_function); 00086 00087 00088 NonlinearSolverT(MatrixType& J, 00089 JacobianBuilder form_jacobian, 00090 FunctionBuilder form_function); 00091 00092 /// Destructor 00093 /** 00094 * This must be called simultaneously by all processes involved in 00095 * the \ref parallel::Communicator "communicator" used for \ref 00096 * NonlinearSolverT() "construction". 00097 */ 00098 ~NonlinearSolverT(void) 00099 { } 00100 00101 protected: 00102 00103 /// A constuctor for children that avoids instantiating an implementation 00104 NonlinearSolverT(void) 00105 : NonlinearSolverInterface<T, I>(), 00106 parallel::WrappedDistributed(), 00107 utility::WrappedConfigurable(), 00108 utility::Uncopyable() 00109 {} 00110 00111 00112 /// Where things really happen 00113 /** 00114 * The Pimpl idiom is used for \ref NonlinearSolverImplementation 00115 * "implementation", so user code is completely independent of the 00116 * underlying library. This class simply provides an interface to a 00117 * specific \ref NonlinearSolverImplementation "implementation". 00118 * 00119 */ 00120 boost::scoped_ptr< NonlinearSolverImplementation<T, I> > p_impl; 00121 00122 /// Get the solution tolerance (specialized) 00123 double p_tolerance(void) const 00124 { 00125 return p_impl->tolerance(); 00126 } 00127 00128 /// Set the solver tolerance (specialized) 00129 void p_tolerance(const double& tol) 00130 { 00131 p_impl->tolerance(tol); 00132 } 00133 00134 /// Get the maximum iterations (specialized) 00135 int p_maximumIterations(void) const 00136 { 00137 return p_impl->maximumIterations(); 00138 } 00139 00140 /// Set the maximum solution iterations (specialized) 00141 void p_maximumIterations(const int& n) 00142 { 00143 p_impl->maximumIterations(n); 00144 } 00145 00146 /// Solve w/ the specified initial estimated, put result in same vector 00147 void p_solve(VectorType& x) 00148 { 00149 p_impl->solve(x); 00150 } 00151 00152 /// Set the implementation 00153 /** 00154 * Does what is necessary to set the \ref 00155 * NonlinearSolverImplementation "implementation". Subclasses are 00156 * required to call this at construction. 00157 * 00158 * @param impl specific nonlinear solver implementation to use 00159 */ 00160 void p_setImpl(NonlinearSolverImplementation<T, I> *impl) 00161 { 00162 p_impl.reset(impl); 00163 p_setDistributed(p_impl.get()); 00164 p_setConfigurable(p_impl.get()); 00165 } 00166 00167 }; 00168 00169 typedef NonlinearSolverT<ComplexType> ComplexNonlinearSolver; 00170 typedef NonlinearSolverT<RealType> RealNonlinearSolver; 00171 typedef ComplexNonlinearSolver NonlinearSolver; 00172 00173 00174 } // namespace math 00175 } // namespace gridpack 00176 00177 00178 #endif